package com.talkyun.utils.loader.utils;

import javax.net.ssl.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class HttpUtils {
    private static class TrustAnyTrustManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private static final String CHARSET = "utf-8";
    private String url;
    private int timeout;

    public HttpUtils(String url, int timeout) {
        this.url = url;
        this.timeout = timeout;
    }

    public String get() throws IOException {
        return this.handle("GET", null);
    }

    public String post(String body) throws IOException {
        return this.handle("POST", body);
    }

    private String handle(String method, String body) throws IOException {
        if (url != null && url.contains(";")) {
            IOException last = null;
            String[] urls = url.split(";");
            for (String url2 : urls) {
                if (this.isBlank(url2)) {
                    continue;
                }
                try {
                    return this.doHandle(url2, method, body);
                } catch (IOException e) {
                    last = e;
                }
            }
            throw last != null ? last : new IOException(url);
        } else {
            return this.doHandle(url, method, body);
        }
    }

    private String doHandle(String url, String method, String body) throws IOException {
        URL url2 = new URL(url);
        HttpURLConnection conn = isHttps(url2) ? getHttpsConn(url2) : (HttpURLConnection) url2.openConnection();

        // socket settings
        conn.setRequestMethod(method);
        if (!"GET".equalsIgnoreCase(method)) {
            conn.setDoOutput(true);
        }
        conn.setDoInput(true);
        conn.setReadTimeout(timeout);
        conn.setConnectTimeout(timeout);
        conn.setUseCaches(false);

        conn.setRequestProperty("Connection", "Keep-Alive");

        // write body
        if (body != null && body.trim().length() != 0) {
            byte[] data = body.getBytes(CHARSET);
            conn.setRequestProperty("Content-Type", "application/json; charset=" + CHARSET);
            conn.setRequestProperty("Content-Length", String.valueOf(data.length));
            conn.getOutputStream().write(data);
        }

        int status = conn.getResponseCode();
        if (status == 200) {
            return this.doRead(conn.getInputStream());
        } else {
            throw new IOException(this.doRead(conn.getErrorStream()));
        }
    }

    private HttpsURLConnection getHttpsConn(URL url) {
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new SecureRandom());
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            return conn;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private String doRead(InputStream is) throws IOException {
        byte[] buf = new byte[1024];
        ByteArrayOutputStream baos = new ByteArrayOutputStream(4 * 1024);
        for (int num; (num = is.read(buf)) != -1; ) {
            baos.write(buf, 0, num);
        }
        return baos.toString(CHARSET);
    }

    private boolean isHttps(URL url) {
        return url.getProtocol().equalsIgnoreCase("https");
    }

    private boolean isBlank(String s) {
        return s == null || s.trim().length() == 0;
    }
}